import React, { Component, cloneElement } from 'react';
import classNames from 'classnames';
import omit from 'omit.js';

export default class Input extends Component {
  static defaultProps = {
    disabled: false,
    prefixCls: 'ant-input',
    type: 'text',
    autosize: false
  };

  constructor(props) {
    super(props);

    const { value = '' } = props;
    this.state = {
      value
    };

    this.handleChange = this.handleChange.bind(this);
    this.handleBlur = this.handleBlur.bind(this);
    this.handleKeyDown = this.handleKeyDown.bind(this);
  }

  componentWillReceiveProps(nextProps) {
    if (nextProps.value !== this.props.value) {
      this.setState({
        value: nextProps.value
      });
    }
  }

  handleBlur(e) {
    const { onBlur } = this.props;
    const data = {
      value: e.target.value,
      field: this.props['data-field']
    };
    if (onBlur) {
      onBlur(data, e);
    }
  }

  handleKeyDown(e) {
    const { onPressEnter, onKeyDown } = this.props;
    const data = {
      value: e.target.value,
      field: this.props['data-field']
    };
    if (e.keyCode === 13 && onPressEnter) {
      onPressEnter(data, e);
    }
    if (onKeyDown) {
      onKeyDown(data, e);
    }
  }

  handleChange(e) {
    const { onChange } = this.props;
    const data = {
      value: e.target.value,
      field: this.props['data-field']
    };
    this.setState({ value: e.target.value });
    if (onChange) {
      onChange(data, e);
    }
  }

  renderLabeledInput(children) {
    const props = this.props;

    if (props.type === 'textarea' || (!props.addonBefore && !props.addonAfter)) {
      return children;
    }

    const wrapperClassName = `${props.prefixCls}-group`;
    const addonClassName = `${wrapperClassName}-addon`;
    const addonBefore = props.addonBefore ? (
      <span className={addonClassName}>
        {props.addonBefore}
      </span>
    ) : null;

    const addonAfter = props.addonAfter ? (
      <span className={addonClassName}>
        {props.addonAfter}
      </span>
    ) : null;

    const className = classNames({
      [`${props.prefixCls}-wrapper`]: true,
      [wrapperClassName]: (addonBefore || addonAfter),
    });

    return (
      <span className={className}>
        {addonBefore}
        {children}
        {addonAfter}
      </span>
    );
  }

  renderLabelIcon(children) {
    const { props } = this;

    if (props.type === 'textarea' || !('prefix' in props || 'suffix' in props)) {
      return children;
    }

    const prefix = props.prefix ? (
      <span className={`${props.prefixCls}-prefix`}>
        {props.prefix}
      </span>
    ) : null;

    const suffix = props.suffix ? (
      <span className={`${props.prefixCls}-suffix`}>
        {props.suffix}
      </span>
    ) : null;

    return (
      <span className={`${props.prefixCls}-preSuffix-wrapper`} style={props.style}>
        {prefix}
        {cloneElement(children, { style: null })}
        {suffix}
      </span>
    );
  }

  renderInput() {
    const { value } = this.state;
    const props = this.props;
    const otherProps = omit(this.props, [
      'prefixCls',
      'onPressEnter',
      'autosize',
      'addonBefore',
      'addonAfter',
      'prefix',
      'suffix',
    ]);

    const inputClassName = classNames(this.props.prefixCls, props.className);
    if (!props.type) {
      return props.children;
    }
    switch (props.type) {
      case 'textarea':
        return (
          <textarea
            {...otherProps}
            className={inputClassName}
            onKeyDown={this.handleKeyDown}
            onChange={this.handleChange}
            value={value}
          />
        );
      default:
        return this.renderLabelIcon(
          <input
            {...otherProps}
            className={inputClassName}
            onKeyDown={this.handleKeyDown}
            onFocus={this.handleFocus}
            onBlur={this.handleBlur}
            onChange={this.handleChange}
            value={value}
          />
        );
    }
  }

  render() {
    return this.renderLabeledInput(this.renderInput());
  }
}
